package com.liveims.webims;

import java.net.MalformedURLException;
import org.apache.log4j.Logger;

import com.alcatel.as.session.distributed.SessionException;

import com.alcatel.sip.client.SipClientFactory;
import com.alcatel.sip.client.SipCredentials;

import com.alcatel.sip.client.register.Binding;
import com.alcatel.sip.client.register.BindingActivationEvent;
import com.alcatel.sip.client.register.BindingTerminationEvent;
import com.alcatel.sip.client.register.RegisterClient;
import com.alcatel.sip.client.register.RegisterClientListener;
import com.liveims.webims.session.IMSManager;
import com.liveims.webims.util.RestPath;
import com.liveims.webims.util.Settings;

import com.nextenso.proxylet.ProxyletConfig;
import com.nextenso.proxylet.ProxyletContext;
import com.nextenso.proxylet.ProxyletException;
import com.nextenso.proxylet.http.BufferedHttpRequestProxylet;
import com.nextenso.proxylet.http.HttpCookie;
import com.nextenso.proxylet.http.HttpHeaders;
import com.nextenso.proxylet.http.HttpRequest;
import com.nextenso.proxylet.http.HttpRequestProlog;
import com.nextenso.proxylet.http.HttpResponse;


public class LoginProxylet implements BufferedHttpRequestProxylet, RegisterClientListener {
	
	private ProxyletContext _context;
	private static final Logger log = Logger.getLogger(LoginProxylet.class);
	RestPath restPath;

	public int doRequest(HttpRequest request) throws ProxyletException {
		String reqMethod = request.getProlog().getMethod();
		String impi = request.getProlog().getParameter("username");
        String password = request.getProlog().getParameter("password");
		//Accept POST to create User's Auth Session
		if (reqMethod.equalsIgnoreCase("POST") ||reqMethod.equalsIgnoreCase("GET")){           
              String user_uri = "sip:"+restPath.getIMPU();
              RegisterClient c;
			try {
				c = SipClientFactory.getInstance().newRegisterClient(user_uri, this);
				c.attach(request);
				
				SipCredentials cred = new SipCredentials(Settings.getInstance().valueOf(Settings.Attribute.IMS_DOMAIN_PROPERTY),
                        impi, password);
				c.addSipCredentials(cred, false);
                c.addRoute("sip:192.168.231.7:5060"); // p-cscf address
                Binding b = c.newBinding(user_uri.split("@")[0]+"@172.27.242.24:5040");
                c.activate(b);
			} catch (MalformedURLException e) {
				e.printStackTrace();
				log.error("unable to register to IMS", e);
			}
	      //to w8 for the response of the sip register
			return BufferedHttpRequestProxylet.SUSPEND;
			
		}else if(reqMethod.equalsIgnoreCase("DELETE")){ //Accept Delete to destroy an Auth Session
			
			return BufferedHttpRequestProxylet.RESPOND_LAST_PROXYLET;
		}else{ //Don't handle other methods
			//TODO
			
			return BufferedHttpRequestProxylet.RESPOND_LAST_PROXYLET;
		}
			
	}

	public int accept(HttpRequestProlog prolog, HttpHeaders headers) {
		String path = prolog.getURL().getPath();
        restPath = new RestPath(path);
        return ACCEPT;
	}

	public void destroy() {
		// TODO Auto-generated method stub

	}

	public String getProxyletInfo() {
		// TODO Auto-generated method stub
		return null;
	}

	public void init(ProxyletConfig cnf) throws ProxyletException {
		_context = cnf.getProxyletContext();
		/*	try {
			Settings.init();
		} catch (Exception e) {
			log.error("***can't initialize the proxylet because of settings "+e);
			e.printStackTrace();
			throw new ProxyletException(e.toString());	
		}*/

	}

	public void bindingsActivated(RegisterClient client,
			BindingActivationEvent event) {
		HttpRequest req = (HttpRequest)client.attachment();
		HttpResponse resp = req.getResponse();
        
        //Reg get 200Ok, then Set the distributed sessions and  the HTTP response should be prepared 
		if(event.isSuccess()){
			log.info("Registrtion to IMS success!");
				
			try {
				String sid = IMSManager.getInstance().createSession("sip:"+restPath.getIMPU());						
			    resp.getHeaders().addCookie(new HttpCookie("sessionid", sid));
			    resp.getProlog().setStatus(200);
			    resp.getProlog().setReason("OK");			    
			    				
			} catch (SessionException e) {
                log.error("session creation fail", e);
				e.printStackTrace();
				resp.getProlog().setStatus(500);
			    resp.getProlog().setReason("Server error: Can't create session for Client");
				
			}
			 _context.resume(req, RESPOND_LAST_PROXYLET);
			 log.info("Http response processing resume");
		}
		
		//when get a challenge 401/407, responds with secrete, to complete the Registration
		/*else {
			int statuscode = event.getSipMessage().getStatus(); 
			if (statuscode == 401 || statuscode ==407){
				SipCredentials cred = new SipCredentials(Settings.getInstance().valueOf(Settings.Attribute.IMS_DOMAIN_PROPERTY),
				                                          impi,
				                                          password);

				RegisterClient c = (RegisterClient)SipClientFactory.getInstance().newAuthenticatedClient(client, event.getSipMessage(), cred);
				setWWWAuth(c, event.getSipMessage(), cred);
				
				/*try {
					c.setFrom("sp:"+impi);
				} catch (MalformedURLException e) {

					e.printStackTrace();
				}
				//c.setRequestHeader("CSeq", "1001", true);
				log.debug(c);
				Binding b = c.newBinding("sip:"+restPath.getIMPU().split("@")[0]+"@172.27.242.24:5040");
				c.attach(req);
				c.activate(b);
				log.debug("****The 2nd REG is sent out*****");
		}*/
	else{
		   log.debug("Registration to IMS failed: "+event.getSipMessage());
		   resp.getProlog().setStatus(500);
		   resp.getProlog().setReason("Server error: Can't create session for Client");
			_context.resume(req, RESPOND_LAST_PROXYLET);
		}
			
	}


	public void bindingsTerminated(RegisterClient client,
			BindingTerminationEvent event) {
		log.debug(client.getTo()+ " Register terminated "+ event.toString());
		
	}
    
	/*
	 * This method is to set the sip request to 401/407 challenge response
	 * @parameter 
	 * @parameter 
	 */
	/*public void setWWWAuth(SipClient c, SipMessage m, SipCredentials cred){
		String a =m.getHeader("WWW-Authenticate");		
		a = a.replaceAll("[ ,]", "\n");
		log.debug("***parsed WWW-Authenticated  " + a);
		Properties paras = new Properties();
		try{
		  paras.load(new ByteArrayInputStream(a.getBytes()));		  
		  String realm = paras.getProperty("realm").replaceAll("\"", "");
		  log.debug(realm);
		  String nonce = paras.getProperty("nonce").replaceAll("\"", "");
		  log.debug(nonce);
		  String qop = paras.getProperty("qop").replaceAll("\"", "");
		  log.debug(qop);
		  
		  //The data that the client should prepare
		  String nonceCount  = "00000001";
		  String cnonce = "0a4f113b";
		  String digest_uri = "sip:"+realm;
		  String userName = cred.getUser();
		  String password = cred.getPassword();
		  
		  //calculate the response 
		  String response = com.liveims.webims.util.Authen.createRep(userName, realm, password, nonce, nonceCount, cnonce, qop, "REGISTER", digest_uri);
	      log.debug("response 1 calculated by servlet: "+response);
	      //prepare the Auth header
	      String authHead = m.getHeader("www-Authenticate");
		  authHead = authHead.replaceFirst("qop=\"auth\"", "qop=auth");		  
		  authHead += ",username=\""+userName+"\",uri=\""+digest_uri+"\",nc="+nonceCount+",cnonce=\"" +cnonce +"\",response=\""+response+"\"";
		  log.debug(authHead);
		  
		  c.setRequestHeader("WWW-Authenticate", m.getHeader("WWW-Authenticate"), false);
		  c.setRequestHeader("Authorization", authHead,false);			
		}catch(Exception e){
			e.printStackTrace();
			log.error("set auth header error", e);			
		}
	}*/

}
